﻿using System;
using System.Linq;
using System.Reflection;
using IInject.Internal;

namespace IInject.Resolution
{
	public class MostResolvableConstructorSelector : DefaultConstructorSelector
	{
		public MostResolvableConstructorSelector(IContainer container) : base(container)
		{
		}

		public override ConstructorDependency Select(TypeDependency type)
		{
			var ctors = GetConstructors(type.Dependent);

			if (ctors.Length == 1)
			{
				if (CanResolveParameters(ctors[0].GetParameters()))
				{
					return new ConstructorDependency(ctors[0]);
				}
			}

			return GetConstructor(type, ctors);
		}

		protected override ConstructorInfo[] GetConstructors(Type type)
		{
			if (type.IsValueType)
			{
				return base.GetConstructors(type);
			}

			var ctor = type.GetConstructors();
			return ctor.OrderByDescending(c => c.GetParameters().Count()).ToArray();
		}

		private ConstructorDependency GetConstructor(TypeDependency type, ConstructorInfo[] ctors)
		{
			ConstructorDependency ctor = Select(ctors);

			if (ctor == null)
			{
				ctor = base.Select(type);

				if (ctor == null)
				{
					Thrower.CannotResolveConstructor(type.Dependent);
				}
			}

			return ctor;
		}
	}
}
